#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
视频压字处理模块
在视频上添加文字并支持动画效果，保留视频原有内容
"""

import os
import sys
from pathlib import Path
import base64
import textwrap
from typing import List, Dict, Any, Union, Tuple, Callable

# 添加src目录到Python路径
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

# 尝试导入moviepy.editor，如果失败则给出提示
try:
    import moviepy
    print(f"检测到 MoviePy 版本: {moviepy.__version__}")
    
    # 根据MoviePy v2.0更新文档，直接从moviepy导入
    from moviepy import VideoFileClip, CompositeVideoClip, TextClip, ImageClip
    # 尝试导入特效函数
    try:
        # MoviePy 2.x 导入方式
        from moviepy.video.fx.fadein import fadein
        from moviepy.video.fx.fadeout import fadeout
    except ImportError:
        # MoviePy 1.x 或其他版本导入方式
        try:
            from moviepy.video.fx import fadein, fadeout
        except ImportError:
            # 如果无法导入特效函数，设置为None
            fadein = None
            fadeout = None
    
    MOVIEPY_AVAILABLE = True
except ImportError as e:
    print(f"无法导入moviepy: {e}")
    print("请确保已正确安装moviepy: pip install moviepy==2.2.1")
    MOVIEPY_AVAILABLE = False

# 尝试导入PIL，如果失败则给出提示
try:
    from PIL import Image, ImageDraw, ImageFont
    PIL_AVAILABLE = True
except ImportError as e:
    print(f"无法导入PIL: {e}")
    PIL_AVAILABLE = False

# 尝试导入OpenCV，如果失败则给出提示
try:
    import cv2
    import numpy as np
    OPENCV_AVAILABLE = True
except ImportError as e:
    print(f"无法导入OpenCV: {e}")
    print("请确保已正确安装opencv-python: pip install opencv-python")
    OPENCV_AVAILABLE = False

# 添加src目录到Python路径
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from src.utils.add_text_logo_to_video import create_text_image, pil_image_to_temp_file


def add_text_to_video(video_path: str, output_path: str, texts: List[Dict[str, Any]]) -> bool:
    """
    在视频上添加文字（支持动画效果）
    
    Args:
        video_path (str): 原始视频路径
        output_path (str): 输出视频路径
        texts (list): 文字配置列表，每个元素为字典，包含:
            - text: 文字内容
            - position: 位置，可以是('center', 'top')这样的元组或自定义函数
            - fontsize: 字体大小
            - color: 字体颜色
            - duration: 持续时间
            - start_time: 开始时间
            - effect: 动画效果（可选）
            - font: 字体（可选）
            - stroke_color: 描边颜色（可选）
            - stroke_width: 描边宽度（可选）
            - max_width: 最大宽度，超过将自动换行（可选）
            - add_shadow: 是否添加阴影（可选）
            - shadow_color: 阴影颜色（可选）
            - shadow_offset: 阴影偏移（可选）
            - video_duration: 是否与视频同长（可选）
        
    Returns:
        bool: 是否成功
    """
    if not MOVIEPY_AVAILABLE or not PIL_AVAILABLE:
        print("缺少必要的依赖库，请检查moviepy和Pillow是否正确安装")
        return False
        
    video = None
    final_video = None
    text_clips = []
    temp_files = []  # 用于存储临时文件路径，以便后续清理
        
    try:
        # 检查视频文件是否存在
        if not os.path.exists(video_path):
            print(f"视频文件不存在: {video_path}")
            return False
            
        # 加载视频
        video = VideoFileClip(video_path)
        width, height = video.size
        
        # 创建文本剪辑
        text_clips = []
        
        # 处理每个文字
        for text_config in texts:
            text = text_config.get('text', '')
            position = text_config.get('position', ('center', 'center'))
            fontsize = text_config.get('fontsize', 40)
            color = text_config.get('color', 'white')
            duration = text_config.get('duration', 5)
            start_time = text_config.get('start_time', 0)
            effect = text_config.get('effect', None)
            font = text_config.get('font', None)
            stroke_color = text_config.get('stroke_color', 'black')
            stroke_width = text_config.get('stroke_width', 1)
            max_width = text_config.get('max_width', width - 100)  # 默认留出一些边距
            add_shadow = text_config.get('add_shadow', False)
            shadow_color = text_config.get('shadow_color', 'black')
            shadow_offset = text_config.get('shadow_offset', (3, 3))
            video_duration_flag = text_config.get('video_duration', False)
            
            # 如果video_duration_flag为True或duration为-1，则设置持续时间与视频相同
            if video_duration_flag or duration == -1:
                duration = video.duration
            
            # 创建文本剪辑
            text_clip = None
            shadow_clip = None
            
            try:
                # 尝试使用PIL创建文本图像，支持更好的换行和特殊字符
                # 构建带换行的文本
                wrapped_text = text
                if max_width:
                    # 使用textwrap进行智能换行
                    lines = []
                    for paragraph in text.split('\n'):
                        if paragraph.strip():  # 跳过空行
                            # 估算每行能容纳的字符数
                            # 字体大小乘以平均字符宽度比例（中文字符约为0.9-1.0，英文为0.6左右）
                            avg_char_width = fontsize * 0.7
                            max_chars = int(max_width / avg_char_width)
                            if max_chars > 0:
                                # 使用textwrap进行换行，break_long_words=True确保长单词也能换行
                                wrapped = textwrap.fill(paragraph, width=max_chars, break_long_words=True, break_on_hyphens=False)
                                lines.append(wrapped)
                            else:
                                lines.append(paragraph)
                    wrapped_text = '\n'.join(lines)
                
                # 创建主文本图像
                text_image = create_text_image(
                    text=wrapped_text,
                    font_size=fontsize,
                    text_color=_color_name_to_rgb(color),
                    stroke_color=_color_name_to_rgb(stroke_color) if stroke_color else (0, 0, 0),
                    stroke_width=stroke_width,
                    max_width=max_width
                )
                
                # 保存图像到临时文件
                temp_image_path = pil_image_to_temp_file(text_image)
                # 使用临时文件创建ImageClip
                text_clip = ImageClip(temp_image_path)
                # 添加临时文件到清理列表
                temp_files.append(temp_image_path)
                
                # 如果需要添加阴影，创建阴影剪辑
                if add_shadow:
                    # 创建阴影图像
                    shadow_image = create_text_image(
                        text=wrapped_text,
                        font_size=fontsize,
                        text_color=_color_name_to_rgb(shadow_color),
                        stroke_color=_color_name_to_rgb(stroke_color) if stroke_color else (0, 0, 0),
                        stroke_width=stroke_width,
                        max_width=max_width
                    )
                    shadow_temp_path = pil_image_to_temp_file(shadow_image)
                    shadow_clip = ImageClip(shadow_temp_path)
                    temp_files.append(shadow_temp_path)
                    
            except Exception as e:
                print(f"使用PIL创建文本失败: {e}")
                continue
            
            # 设置文本剪辑的位置和持续时间
            # 根据MoviePy版本使用不同的方法
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x 使用 with_ 前缀的方法
                text_clip = text_clip.with_position(position)
                if shadow_clip:
                    # 阴影位置相对于主文本偏移
                    shadow_position = (
                        position[0] + shadow_offset[0] if isinstance(position[0], (int, float)) else position[0],
                        position[1] + shadow_offset[1] if isinstance(position[1], (int, float)) else position[1]
                    )
                    shadow_clip = shadow_clip.with_position(shadow_position)
            else:
                # MoviePy 1.x 使用 set_ 前缀的方法
                text_clip = text_clip.set_position(position)
                if shadow_clip:
                    # 阴影位置相对于主文本偏移
                    shadow_position = (
                        position[0] + shadow_offset[0] if isinstance(position[0], (int, float)) else position[0],
                        position[1] + shadow_offset[1] if isinstance(position[1], (int, float)) else position[1]
                    )
                    shadow_clip = shadow_clip.set_position(shadow_position)
            
            if hasattr(text_clip, 'with_duration'):
                # MoviePy 2.x
                text_clip = text_clip.with_duration(duration)
                if shadow_clip:
                    shadow_clip = shadow_clip.with_duration(duration)
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_duration(duration)
                if shadow_clip:
                    shadow_clip = shadow_clip.set_duration(duration)

            # 如果有开始时间，则设置开始时间
            if start_time > 0:
                if hasattr(text_clip, 'with_start'):
                    # MoviePy 2.x
                    text_clip = text_clip.with_start(start_time)
                    if shadow_clip:
                        shadow_clip = shadow_clip.with_start(start_time)
                else:
                    # MoviePy 1.x
                    text_clip = text_clip.set_start(start_time)
                    if shadow_clip:
                        shadow_clip = shadow_clip.set_start(start_time)
            
            # 添加动画效果
            if effect == 'fadein' and fadein is not None:
                text_clip = fadein(text_clip, 0.5)
                if shadow_clip:
                    shadow_clip = fadein(shadow_clip, 0.5)
            elif effect == 'fadeout' and fadeout is not None:
                text_clip = fadeout(text_clip, 0.5)
                if shadow_clip:
                    shadow_clip = fadeout(shadow_clip, 0.5)
            elif effect == 'fadeinout' and fadein is not None and fadeout is not None:
                text_clip = fadeout(fadein(text_clip, 0.5), 0.5)
                if shadow_clip:
                    shadow_clip = fadeout(fadein(shadow_clip, 0.5), 0.5)
            
            # 先添加阴影剪辑（在主文本下方），再添加主文本剪辑
            if shadow_clip:
                text_clips.append(shadow_clip)
            text_clips.append(text_clip)
        
        # 合成最终视频
        final_clips = [video] + text_clips
        final_video = CompositeVideoClip(final_clips)
        
        # 确保输出目录存在
        output_dir = os.path.dirname(output_path)
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
        
        # 输出视频
        print(f"正在生成视频: {output_path}")
        final_video.write_videofile(
            output_path,
            codec='libx264',
            audio_codec='aac',
            preset='ultrafast',  # 关键！从 medium → ultrafast
            threads=8,           # 不要设 32，8~16 更稳定
            bitrate='8000k'
        )        
        return True
    except Exception as e:
        print(f"在视频上添加文字时出错: {e}")
        return False
    finally:
        # 关闭视频剪辑以释放资源
        if video:
            video.close()
        if final_video:
            final_video.close()
        for clip in text_clips:
            if clip:
                clip.close()


def add_animated_text_to_video(video_path: str, output_path: str, text: str, 
                               animation_type: str = 'slide_from_left') -> bool:
    """
    在视频上添加带动画效果的文字
    
    Args:
        video_path (str): 原始视频路径
        output_path (str): 输出视频路径
        text (str): 要添加的文字
        animation_type (str): 动画类型:
            - 'slide_from_left': 从左侧滑入
            - 'slide_from_right': 从右侧滑入
            - 'slide_from_top': 从顶部滑入
            - 'slide_from_bottom': 从底部滑入
            - 'zoom_in': 放大出现
            - 'zoom_out': 缩小出现
        
    Returns:
        bool: 是否成功
    """
    if not MOVIEPY_AVAILABLE or not PIL_AVAILABLE:
        print("缺少必要的依赖库，请检查moviepy和Pillow是否正确安装")
        return False
        
    video = None
    final_video = None
    text_clip = None
        
    try:
        # 检查视频文件是否存在
        if not os.path.exists(video_path):
            print(f"视频文件不存在: {video_path}")
            return False
            
        # 加载视频
        video = VideoFileClip(video_path)
        width, height = video.size
        
        # 创建文本剪辑
        try:
            # 尝试使用系统中的ARIALUNI.TTF字体来支持特殊字符和emoji
            arialuni_path = "C:\\Windows\\Fonts\\ARIALUNI.TTF"
            segoeui_path = "C:\\Windows\\Fonts\\segoeui.ttf"
            
            # 检查可用的字体
            font = None
            if os.path.exists(arialuni_path):
                font = arialuni_path
            elif os.path.exists(segoeui_path):
                font = segoeui_path
            
            # 构建TextClip参数
            text_clip_params = {
                'text': text,
                'font_size': 80,
                'color': 'white',
                'stroke_color': 'black',
                'stroke_width': 2,
                'size': (width, 200)
            }
            
            # 如果有可用字体，添加到参数中
            if font:
                text_clip_params['font'] = font
                
            text_clip = TextClip(**text_clip_params)
        except Exception as e:
            print(f"创建文本剪辑时出错: {e}")
            # 尝试使用默认字体
            try:
                text_clip = TextClip(text=text, font_size=80, color='white', stroke_color='black', stroke_width=2, font="Arial")
            except Exception as e2:
                print(f"使用默认字体也失败: {e2}")
                return False
        
        # 根据动画类型设置动画效果
        if animation_type == 'slide_from_left':
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(lambda t: (min(width * t / video.duration, (width - text_clip.w) // 2), height // 4))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(lambda t: (min(width * t / video.duration, (width - text_clip.w) // 2), height // 4))
        elif animation_type == 'slide_from_right':
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(lambda t: (max(width - width * t / video.duration, (width - text_clip.w) // 2), height // 4))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(lambda t: (max(width - width * t / video.duration, (width - text_clip.w) // 2), height // 4))
        elif animation_type == 'slide_from_top':
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(lambda t: ((width - text_clip.w) // 2, min(height * t / video.duration, height // 4)))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(lambda t: ((width - text_clip.w) // 2, min(height * t / video.duration, height // 4)))
        elif animation_type == 'slide_from_bottom':
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(lambda t: ((width - text_clip.w) // 2, max(height - height * t / video.duration, height // 4)))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(lambda t: ((width - text_clip.w) // 2, max(height - height * t / video.duration, height // 4)))
        elif animation_type == 'zoom_in':
            if hasattr(text_clip, 'resized'):
                # MoviePy 2.x 使用 resized
                text_clip = text_clip.resized(lambda t: 0.5 + 0.5 * t / video.duration)
            else:
                # MoviePy 1.x 使用 resize
                text_clip = text_clip.resize(lambda t: 0.5 + 0.5 * t / video.duration)
            
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(('center', height // 4))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(('center', height // 4))
        elif animation_type == 'zoom_out':
            if hasattr(text_clip, 'resized'):
                # MoviePy 2.x 使用 resized
                text_clip = text_clip.resized(lambda t: 1.5 - 0.5 * t / video.duration)
            else:
                # MoviePy 1.x 使用 resize
                text_clip = text_clip.resize(lambda t: 1.5 - 0.5 * t / video.duration)
            
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(('center', height // 4))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(('center', height // 4))
        else:
            # 默认位置
            if hasattr(text_clip, 'with_position'):
                # MoviePy 2.x
                text_clip = text_clip.with_position(('center', height // 4))
            else:
                # MoviePy 1.x
                text_clip = text_clip.set_position(('center', height // 4))
        
        if hasattr(text_clip, 'with_duration'):
            # MoviePy 2.x
            text_clip = text_clip.with_duration(video.duration)
        else:
            # MoviePy 1.x
            text_clip = text_clip.set_duration(video.duration)
        
        # 合成最终视频
        final_video = CompositeVideoClip([video, text_clip])
        
        # 确保输出目录存在
        output_dir = os.path.dirname(output_path)
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
        
        # 输出视频
        print(f"正在生成视频: {output_path}")
        final_video.write_videofile(output_path, codec='libx264', audio_codec='aac', threads=8)
            
        return True
    except Exception as e:
        print(f"在视频上添加动画文字时出错: {e}")
        return False
    finally:
        # 关闭视频剪辑以释放资源
        if video:
            video.close()
        if final_video:
            final_video.close()
        if text_clip:
            text_clip.close()


def add_text_to_video_with_opencv(video_path: str, output_path: str, texts: List[Dict[str, Any]]) -> bool:
    """
    使用OpenCV在视频上添加文字（支持emoji）
    
    Args:
        video_path (str): 原始视频路径
        output_path (str): 输出视频路径
        texts (list): 文字配置列表，每个元素为字典，包含:
            - text: 文字内容
            - position: 位置，可以是('center', 'top')这样的元组
            - fontsize: 字体大小
            - color: 字体颜色 (B, G, R) 格式
            - duration: 持续时间（秒）
            - start_time: 开始时间（秒）
            - background_color: 文本背景颜色 (B, G, R, A) 格式（可选）
            - background_padding: 背景填充（可选）
            - max_width: 最大宽度，超过将自动换行（可选）
        
    Returns:
        bool: 是否成功
    """
    if not OPENCV_AVAILABLE:
        print("缺少必要的依赖库，请检查OpenCV是否正确安装")
        return False
    
    # 检查PIL是否可用
    if not PIL_AVAILABLE:
        print("缺少必要的依赖库，请检查Pillow是否正确安装")
        return False
    
    cap = None
    out = None
    
    try:
        # 打开视频文件
        cap = cv2.VideoCapture(video_path)
        if not cap.isOpened():
            print(f"无法打开视频文件: {video_path}")
            return False
        
        # 获取视频属性
        fps = cap.get(cv2.CAP_PROP_FPS)
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        
        # 创建视频写入对象
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
        
        # 处理每一帧
        frame_index = 0
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break
            
            # 计算当前时间（秒）
            current_time = frame_index / fps
            
            # 在当前帧上添加文本
            for text_config in texts:
                text = text_config.get('text', '')
                position = text_config.get('position', ('center', 'center'))
                fontsize = text_config.get('fontsize', 30)
                color = text_config.get('color', (255, 255, 255))  # OpenCV使用BGR格式
                duration = text_config.get('duration', 5)
                start_time = text_config.get('start_time', 0)
                background_color = text_config.get('background_color', None)
                background_padding = text_config.get('background_padding', 5)
                max_width = text_config.get('max_width', width - 100)
                
                # 检查是否应该显示此文本
                if current_time >= start_time and current_time <= (start_time + duration):
                    # 使用PIL创建带emoji的文本图像
                    try:
                        # 创建文本图像
                        text_image = create_text_image(
                            text=text,
                            font_size=fontsize,
                            text_color=color[::-1],  # 转换BGR到RGB
                            stroke_color=(0, 0, 0),
                            stroke_width=10,
                            max_width=max_width,
                            line_spacing=4.2  # 添加行间距支持，默认1.2倍行距
                        )
                        
                        if text_image:
                            # 将PIL图像转换为OpenCV格式
                            # 首先转换为numpy数组
                            text_array = np.array(text_image)
                            # 转换RGBA到BGRA（OpenCV使用BGR）
                            if text_array.shape[2] == 4:  # 包含alpha通道
                                text_bgra = cv2.cvtColor(text_array, cv2.COLOR_RGBA2BGRA)
                            else:
                                text_bgra = cv2.cvtColor(text_array, cv2.COLOR_RGB2BGR)
                            
                            # 处理位置参数
                            x, y = position
                            text_height, text_width = text_bgra.shape[:2]
                            
                            if x == 'center':
                                x = (width - text_width) // 2
                            elif x == 'left':
                                x = 10
                            elif x == 'right':
                                x = width - text_width - 10
                            else:
                                x = int(x)
                            
                            if y == 'center':
                                y = (height - text_height) // 2
                            elif y == 'top':
                                y = 50
                            elif y == 'bottom':
                                y = height - text_height - 50
                            else:
                                y = int(y)
                            
                            # 确保位置在图像边界内
                            x = max(0, min(x, width - text_width))
                            y = max(0, min(y, height - text_height))
                            
                            # 绘制背景
                            if background_color:
                                bg_x1 = x - background_padding
                                bg_y1 = y - background_padding
                                bg_x2 = x + text_width + background_padding
                                bg_y2 = y + text_height + background_padding
                                
                                # 确保背景矩形在图像边界内
                                bg_x1 = max(0, bg_x1)
                                bg_y1 = max(0, bg_y1)
                                bg_x2 = min(width, bg_x2)
                                bg_y2 = min(height, bg_y2)
                                
                                # 创建背景图像
                                if len(background_color) == 4:  # 包含透明度
                                    alpha = background_color[3] / 255.0
                                    # 混合背景与原图像
                                    if bg_y2 > bg_y1 and bg_x2 > bg_x1:
                                        roi = frame[bg_y1:bg_y2, bg_x1:bg_x2]
                                        background_bgr = np.full(roi.shape, background_color[:3], dtype=np.uint8)
                                        cv2.addWeighted(roi, 1 - alpha, background_bgr, alpha, 0, roi)
                                        frame[bg_y1:bg_y2, bg_x1:bg_x2] = roi
                                else:
                                    cv2.rectangle(frame, (bg_x1, bg_y1), (bg_x2, bg_y2), background_color, -1)
                            
                            # 将文本图像叠加到视频帧上
                            if y + text_height <= height and x + text_width <= width:
                                # 提取文本图像的alpha通道（如果存在）
                                if text_bgra.shape[2] == 4:  # BGRA格式
                                    # 分离BGR和Alpha通道
                                    text_bgr = text_bgra[:, :, :3]
                                    alpha_channel = text_bgra[:, :, 3] / 255.0
                                    
                                    # 创建要覆盖的区域
                                    roi = frame[y:y+text_height, x:x+text_width]
                                    
                                    # 使用alpha混合
                                    for c in range(3):  # 对每个颜色通道进行混合
                                        roi[:, :, c] = (1.0 - alpha_channel) * roi[:, :, c] + alpha_channel * text_bgr[:, :, c]
                                    
                                    # 将混合后的结果写回原图像
                                    frame[y:y+text_height, x:x+text_width] = roi
                                else:
                                    # 直接覆盖（无透明度）
                                    frame[y:y+text_height, x:x+text_width] = text_bgra
                    except Exception as e:
                        print(f"处理文本时出错: {e}")
                        # 出错时使用原始OpenCV方法作为后备
                        try:
                            # 简单的文本换行处理
                            if len(text) > 40:  # 粗略估算换行点
                                wrapped_lines = textwrap.wrap(text, width=40)
                            else:
                                wrapped_lines = [text]
                            
                            # 处理位置参数
                            x, y = position
                            line_height = int(fontsize * 1.5)
                            
                            if x == 'center':
                                max_text_width = 0
                                for line in wrapped_lines:
                                    text_size = cv2.getTextSize(line, cv2.FONT_HERSHEY_SIMPLEX, fontsize/30, 1)[0]
                                    max_text_width = max(max_text_width, text_size[0])
                                x = (width - max_text_width) // 2
                            elif x == 'left':
                                x = 10
                            elif x == 'right':
                                max_text_width = 0
                                for line in wrapped_lines:
                                    text_size = cv2.getTextSize(line, cv2.FONT_HERSHEY_SIMPLEX, fontsize/30, 1)[0]
                                    max_text_width = max(max_text_width, text_size[0])
                                x = width - max_text_width - 10
                            else:
                                x = int(x)
                            
                            if y == 'center':
                                text_height = len(wrapped_lines) * line_height
                                y = (height - text_height) // 2
                            elif y == 'top':
                                y = 50
                            elif y == 'bottom':
                                text_height = len(wrapped_lines) * line_height
                                y = height - text_height - 50
                            else:
                                y = int(y)
                            
                            # 为每行文本绘制文本
                            for i, line in enumerate(wrapped_lines):
                                line_y = y + i * line_height
                                cv2.putText(frame, line, (x, line_y), cv2.FONT_HERSHEY_SIMPLEX, 
                                           fontsize/30, color, 1, cv2.LINE_AA)
                        except Exception as e2:
                            print(f"后备文本处理也失败了: {e2}")
            
            # 写入帧到输出视频
            out.write(frame)
            frame_index += 1
        
        # 释放资源
        cap.release()
        out.release()
        cv2.destroyAllWindows()
        
        print(f"成功生成视频: {output_path}")
        return True
        
    except Exception as e:
        print(f"使用OpenCV处理视频时出错: {e}")
        # 确保释放资源
        if cap:
            cap.release()
        if out:
            out.release()
        cv2.destroyAllWindows()
        return False


def _color_name_to_rgb(color_name):
    """将颜色名称转换为RGB值"""
    color_map = {
        'white': (255, 255, 255),
        'black': (0, 0, 0),
        'red': (255, 0, 0),
        'green': (0, 255, 0),
        'blue': (0, 0, 255),
        'yellow': (255, 255, 0),
        'cyan': (0, 255, 255),
        'magenta': (255, 0, 255)
    }
    # 如果是十六进制颜色值
    if isinstance(color_name, str) and color_name.startswith('#'):
        try:
            hex_color = color_name.lstrip('#')
            return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
        except:
            pass
    
    return color_map.get(color_name, (255, 255, 255))  # 默认白色
